/**
 * Author: luoqi
 * Created Date: 2025-11-12 01:09:15
 * Last Modified: 2025-11-15 03:31:40
 * Modified By: luoqi at <**@****>
 * Copyright (c) 2025 <*****>
 * Description:
 */

#include <tim.h>
#include "tim_port.h"

static TimVal enc2_val, enc3_val, tim4_val;

int tim_start(TimPort port)
{
    switch(port) {
    case TIM_PORT_PWM1:
        HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
        HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
        HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
        HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_4);
        break;
    case TIM_PORT_ENC2:
        __HAL_TIM_SET_COUNTER(&htim2, 0);
        HAL_TIM_Base_Start_IT(&htim2);
        HAL_TIM_Encoder_Start_IT(&htim2, TIM_CHANNEL_1 | TIM_CHANNEL_2);
        enc2_val.count = 0;
        enc2_val.overflow = 0;
        break;
    case TIM_PORT_ENC3:
        __HAL_TIM_SET_COUNTER(&htim3, 0);
        HAL_TIM_Base_Start_IT(&htim3);
        HAL_TIM_Encoder_Start_IT(&htim3, TIM_CHANNEL_1 | TIM_CHANNEL_2);
        enc3_val.count = 0;
        enc3_val.overflow = 0;
        break;
    case TIM_PORT_TIM4:
        tim4_val.count = 0;
        tim4_val.overflow = 0;
        HAL_TIM_Base_Start_IT(&htim4);
        break;
    default:
        return -1;
    }
    return 0;
}

int tim_stop(TimPort port)
{
    switch(port) {
    case TIM_PORT_PWM1:
        HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_1);
        HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_2);
        HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_3);
        HAL_TIM_PWM_Stop(&htim1, TIM_CHANNEL_4);
        break;
    case TIM_PORT_ENC2:
        HAL_TIM_Encoder_Stop_IT(&htim2, TIM_CHANNEL_1 | TIM_CHANNEL_2);
        break;
    case TIM_PORT_ENC3:
        HAL_TIM_Encoder_Stop_IT(&htim3, TIM_CHANNEL_1 | TIM_CHANNEL_2);
        break;
    case TIM_PORT_TIM4:
        HAL_TIM_Base_Stop_IT(&htim4);
        break;
    default:
        return -1;
    }
    return 0;
}

int tim_pwm_set(TimPort port, PwmChannel ch, uint16_t duty)
{
    switch(port) {
    case TIM_PORT_PWM1:
        switch(ch) {
        case PWM_CH1:
            __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, duty);
            break;
        case PWM_CH2:
            __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_2, duty);
            break;
        case PWM_CH3:
            __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_3, duty);
            break;
        case PWM_CH4:
            __HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_4, duty);
            break;
        default:
            return -1;
        }
        break;
    default:
        return -1;
    }
    return 0;
}

int tim_get(TimPort port, TimVal *val)
{
    switch(port) {
    case TIM_PORT_ENC3:
        val->count = __HAL_TIM_GET_COUNTER(&htim3);
        val->overflow = enc3_val.overflow;
        break;
    case TIM_PORT_TIM4:
        val->count = __HAL_TIM_GET_COUNTER(&htim4);
        val->overflow = tim4_val.overflow;
        break;
    default:
        return -1;
    }
    return 0;
}

void tim4_set_it_period(uint32_t us)
{
    __HAL_TIM_SET_AUTORELOAD(&htim4, us - 1);
}

#include <io_port.h>
#include <stdbool.h>

__weak void tim4_it_cb_overide(void)
{
    
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim->Instance == TIM2) {
        if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) {
            enc2_val.overflow--;
        } else {
            enc2_val.overflow++;
        }
    }

    if(htim->Instance == TIM3) {
        if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) {
            enc3_val.overflow--;
        } else {
            enc3_val.overflow++;
        }
    }
    
    if(htim->Instance == TIM4) {
        tim4_it_cb_overide();
        if(__HAL_TIM_IS_TIM_COUNTING_DOWN(htim)) {
            tim4_val.overflow--;
        } else {
            tim4_val.overflow++;
        }
    }
}
